{-
 This file is part of the Clafer to Alloy Translator (clafer2alloy).

 Copyright (C) 2010 Kacper Bak <http://gsd.uwaterloo.ca/kbak>

 clafer2alloy is free software: you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 clafer2alloy is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public License
 along with clafer2alloy. (See files COPYING and COPYING.LESSER.)  If not,
 see <http://www.gnu.org/licenses/>.
-}
module Renamer where

import Absclafer2alloy
import Common
import TypeEngine
import AlloyCode
import Data.Maybe
import Data.Map (Map)
import qualified Data.Map as Map

-- -----------------------------------------------------------------------------
-- environment carries predecessors
data REnv = REnv [Ident] SymbolTable

renameModule :: SymbolTable -> Module -> Module
renameModule st x = case x of
  Module declarations  -> Module $
    map (renameDeclaration (REnv [] st)) declarations


renameDeclaration :: REnv -> Declaration -> Declaration
renameDeclaration env@(REnv predecessors st) x = case x of
  EnumDecl ident enumids  -> error "desugared"
  AbsClaferDecl gcard ident super attr elements  ->
    AbsClaferDecl gcard (renameIdent env ident) (renameSuper env super) attr
                  (renameElements env' elements)
    where
    env' = REnv (ident : predecessors) st
  ClaferDecl clafer  -> ClaferDecl $ renameClafer env clafer
  ConstDecl constraint  -> x


renameIdent :: REnv -> Ident -> Ident
renameIdent (REnv predecessors st) ident =
  lookupSymName (ident : predecessors) st


renameSuper :: REnv -> Super -> Super
renameSuper (REnv predecessors st) x = case x of
  SuperEmpty  -> error "desugared"
  Super (Name modids ident)  ->
    if baseClafer == transIdent ident then x
    else Super $ Name modids $ lookupSymName [ident] st


-- renames non-abstract clafer
renameClafer :: REnv -> Clafer -> Clafer
renameClafer env@(REnv predecessors st) x = case x of
  Clafer gcard ident super attr essential card elements  ->
    Clafer gcard (renameIdent env ident) (renameSuper env super) attr
           essential card (renameElements env' elements)
       where
       env' = REnv (ident : predecessors) st 


-- renames subclafers
renameElements :: REnv -> Elements -> Elements
renameElements env x = case x of
  ElementsEmpty  -> error "desugred"
  Elements elements  -> Elements $ map (renameElement env) elements


-- renames single subclafer
renameElement :: REnv -> Element -> Element
renameElement env x = case x of
  Subclafer clafer  -> Subclafer $ renameClafer env clafer
  ClaferUse name essential card elements -> error "desugared"
  Subconstraint constraint  -> x
